﻿using System;
using System.Configuration;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;

namespace Kaio.Core.Media
{
    public class ImageHandler : IHttpHandler
    {
       
      private static Size GetSize(HttpContext context)
      {

          int _height = 0;
          int _width = 0;

          int.TryParse(context.Request["h"], out _height);
          int.TryParse(context.Request["w"], out _width);

          if (context.Request["size"] != null)
          {
              int _size;
              int.TryParse(context.Request["size"], out _size);

              _width = _height = _size;
          }


          return new Size(_width, _height);
      }

      private static string GetFilePath(HttpContext context)
      {
          var _photoName = context.Request.QueryString["f"] ?? context.Request.QueryString[0];

          if (string.IsNullOrEmpty(_photoName) || _photoName == "notfound" || _photoName == "notfound.jpg")
          {

              return null;
          }


          var _f = _photoName.Substring(0, _photoName.IndexOf(".", StringComparison.Ordinal));

          long _date;


          long.TryParse(_f, out _date);


          if (long.TryParse(_f, out _date))
          {
              var  _d = new DateTime(_date);
              string _subPhotoPath = _d.ToString("yyyy/MM/dd");
              return Path.Combine( _subPhotoPath, _photoName);

          }
          return _photoName;


      }
        public void ProcessRequest(HttpContext context)
        {
            string _filePath = GetFilePath(context);

            if (string.IsNullOrEmpty(_filePath) || !ImageHelper.IsGraphic(_filePath))
            {
                context.Response.Redirect("/blank.gif");
                return;
            }

           
            string _subPath =context.Request.AppRelativeCurrentExecutionFilePath.ToLower().Replace("img.ashx",string.Empty); //string.Join("\\", url.Segments.Take(url.Segments.Length - 1).ToArray());

            string _cachePath= _filePath = Path.Combine(HttpRuntime.AppDomainAppPath, ConfigurationManager.AppSettings["UPLOAD_PATH"],_subPath, _filePath);

            var _size = GetSize(context);


            if (_size.Width != 0 || _size.Height != 0)
            {
                string _s = string.Format(".{0}x{1}", _size.Width, _size.Height);

                string _x = context.Request["rotate"];

                _s += !string.IsNullOrEmpty(_x) ? "x" + _x : string.Empty;

                _x = context.Request["zoom"];

                _s += !string.IsNullOrEmpty(_x) ? "x" + _x : string.Empty;

                _x = context.Request["greyscale"];

                _s += !string.IsNullOrEmpty(_x) ? "xGreyscale" + _x : string.Empty;

                _cachePath = Path.Combine(HttpRuntime.AppDomainAppPath,ConfigurationManager.AppSettings["THUMBNAIL_PATH"],_filePath.Insert(_filePath.LastIndexOf(".", StringComparison.Ordinal), _s));
                                          
            }


            string eTag = "\"" + _cachePath.GetHashCode() + "\"";
            if (CheckETag(context, eTag))
            {
                return;
            }

            ImageFormat _imageFormat = GetImageFormat(Path.GetExtension(_filePath));


            byte[] imageData = FileHelper.Read(_cachePath);
            if (imageData == null)
            {

                //var _source = context.Server.MapPath(UploadPath+ filePath);
             //   var _source = Path.Combine(HttpRuntime.AppDomainAppPath, ConfigurationManager.AppSettings["UPLOAD_PATH"], _filePath);
                ImageHelper.ResizeImage(_filePath, _cachePath, _size);
                imageData = FileHelper.Read(_cachePath);

            }

            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Cache.SetETag(eTag);
            context.Response.Cache.SetExpires(DateTime.Now.AddYears(1));
            context.Response.ContentType = "image/" + _imageFormat.ToString().ToLower();
            context.Response.AppendHeader("Content-Length", imageData.Length.ToString());
            context.Response.OutputStream.Write(imageData, 0, imageData.Length);
            context.Response.Flush();
            
        }


        #region Class Methods

        /// <summary>
        /// Check if the ETag that sent from the client is match to the current ETag.
        /// If so, set the status code to 'Not Modified' and stop the response.
        /// </summary>
        private static bool CheckETag(HttpContext context, string eTagCode)
        {
            string ifNoneMatch = context.Request.Headers["If-None-Match"];
            if (eTagCode.Equals(ifNoneMatch, StringComparison.Ordinal))
            {
                context.Response.AppendHeader("Content-Length", "0");
                context.Response.StatusCode = (int)HttpStatusCode.NotModified;
                context.Response.StatusDescription = "Not modified";
                context.Response.SuppressContent = true;
                context.Response.Cache.SetCacheability(HttpCacheability.Public);
                context.Response.Cache.SetETag(eTagCode);
                context.Response.Cache.SetExpires(DateTime.Now.AddYears(1));
                context.Response.End();
                return true;
            }

            return false;
        }
       

        private static ImageFormat GetImageFormat(string extension)
        {
            switch (extension)
            {
                case "JPG":
                case "JPEG":
                    return ImageFormat.Jpeg;
                case "GIF":
                    return ImageFormat.Gif;
                case "BMP":
                    return ImageFormat.Bmp;
                case "PNG":
                    return ImageFormat.Png;
                case "TIFF":
                case "TIF":
                    return ImageFormat.Tiff;
                default:
                    return ImageFormat.Jpeg;
            }
        }

        #endregion
        public bool IsReusable
        {
            get { return true; }
        }
    }
}
